Jonny D’s C++ Tutorial

January 13th, 2010 by Tim Jones Leave a reply »

The following tutorial was created by Blue Dino Code, for the purpose of helping people like you learn SDL. This tutorial, though not purposely a part of the SDLTutorials.com or created for the series, may be a branch or addition to the series. Please read notes by the author for any additional code and/or framework used by the author. SDLTutorials.com does not endorse or reject any of the coding practices outlined in the tutorial, and is not responsible for any code or files belonging to this tutorial that harms your computer.


/*

////////////////////////  C++ From Start to Classes  \\\\\\\\\\\\\\\\\\\\\\\\\\
——————————————————————————-
| Hi, this is Jonny D and I’ll be whirling you through the basics and some    |
| intricacies of C++.  This tutorial is for ABSOLUTE BEGINNERS that are       |
| computer literate.  I’ll try my best to keep it plain, but if anything      |
| isn’t clear, feel free to drop me a line at GrimFang4@hotmail.com .         |
| Stick with me and you’ll be programming in no time.  I’m currently using    |
| the Code::Blocks IDE (Integrated Development Environment) to write and      |
| compile my code under Windows XP and I use the SDL (Simple DirectMedia      |
| Layer) graphics library for my games.  I highly recommend SDL for when you  |
| feel ready to make video games.  I might leave little bits of information   |
| about SDL along the way towards our learning goal.  To keep it simple, I    |
| won’t be referencing any specific programming language other than C and C++ |
| and I won’t be giving any history lessons (yay!).  From here on out, it’s   |
| pure C++ learning time.                                                     |
|                                                                             |
| Well, let’s get started.                                                    |
——————————————————————————-
*/
 

/*
First of all, you’ll need a compiler to convert your code into an executable.
Until Code::Blocks releases a new and bug-free version of their IDE, I
suggest Dev-C++ for beginning C++ programming.  It can be found and downloaded
for free at www.bloodshed.net

Strictly speaking, Dev-C++ is not a compiler, it is an IDE that contains a
particular compiler (in this case, g++).  Dev-C++ is mostly an editor that makes
it easy for you to write your programs.  Whatever you do, don’t use programs
like Word to write your code.  If you don’t have access to a C++ editor like
Dev-C++, then use something simple like Notepad.  Word will leave messy
formatting stuff in your text which will prevent you from compiling your code.

Once you install Dev-C++, you can run it and start coding.  You can open this
file in there as well.  You might need to make a new project and add these code
files to it.
*/

/*
So, what you’ve just seen is the beginning of a multi-line (or C-style)
comment.  This comment starts with a forward slash and an asterisk and is
ended by the reverse, an asterisk and a forward slash.  Whatever is
within a comment is totally ignored by the compiler (the program that changes
the code that you’ve written into a program that the computer can read).  
The easy way to make these comments is to use the numpad’s keys since they are
right next to each other and don’t require a shift modifier.
*/

// This is a single-line (or C++-style or new-style) comment.  It starts with
// two forward slashes and ends at the end of a line.  It’s really quick to
// use for leaving notes in your code, but can be annoying for large blocks of
// writing like I’ll be using for some of my explanations.

/*
C++ uses preprocessor directives.  These are just special keywords that are
checked before the actual code gets compiled.  The most common is the #include
("pound include") preprocessor directive.  It is used to link other source code
files (like this one) to the current source file so that they get compiled
together.  This means you can use the code in the other files just as if it
were in your file.  It is usually best to write your preprocessor directives
at the beginning of your source code file.
*/

#include <cstdlib>  //This line includes a standard header file named "cstdlib",
// the C Standard Library.  This contains many features that help with most
// simple tasks.  This and the next #include are not really necessary in this
// tutorial, but can be useful in some projects.

#include <cstdio>  //"cstdio", the C Standard Input and Output file, gives us
// access to C’s old way of controlling input and output.  Hey, it’s old but
// can still come in handy!

#include <iostream>  //This is C++’s standard input/output file.  It makes
// many things easier and uses a different syntax (order of words/symbols)
// than the C way of things.

#include <string> //Here’s C++’s string class that replaces many uses of C’s
// outdated character arrays (which we’ll see later).  Strings are just a
// bunch of sequential characters (letters/numbers/symbols).  Strings are
// usually seen with double quotes around them, like "This is a string." or
// "1357".

#include "ClassName.h"  //This is a user-defined header file that I made.  
// Notice that it uses a string that contains the name of a file in the same
// directory as this source file.  If this were in a separate folder, I could
// use relative path names like:
       // "folder/ClassName.h"
       //        or
       // "../ClassName.h"
// That last one looks for ClassName in the parent folder of the one
// that JDTutorial.cpp is in.

#define ONE 1  //"Pound define" is another preprocessor directive.  If the first
// term after it, ONE, is found in your code, then it will be converted to the
// second term, 1, before any code is actually compiled.

#define MOOCOW "milk"  // "milk" and 1 are called "literals" because they don’t
// evaluate (break down or change) to anything simpler than themselves.  They
// are hard-written into the code.

#if 0  //The "pound if" is a preprocessor logic control.  You should know that
// 0 means false and 1 means true.  Remember that.  So since 0 means false,
// the next part will not be compiled, thankfully.  If I wanted it to compile,
// I could have written either 1 or ONE, since ONE is #defined as 1.
#include "thisFileDoesNotExist.h"
#else  //Pound else handles the case that the term after the #if is false.
#define SAMURAI "choppity-chop!"
#endif  //Every good if statement must come to an end…

using namespace std;  //This statement is the use of the standard namespace.  
// Namespaces are just protection from colliding definitions.  C++ won’t like
// it if you use the same name for two functions (a function is a
// reusable organizational unit of code, similar to math functions), so
// namespaces will free you from possible collisions, say, with #included code.
// The standard namespace is what many important files (like <iostream>) use
// to store their commands in.  You’ll need to be using this namespace in order
// to use these commands.  Typically, namespaces other than std are only used
// in gigantic projects like operating systems and such.

// Unlike English, where statements are ended with a period, C++ is a language
// where statements are ended with semicolons.  All of your statements must end
// with a semicolon because "whitespace" doesn’t matter to C++.  Tabs, spaces,
// and even carriage returns (end of line, beginning of new line) are ignored
// by the compiler (except for when they separate words) and serve only to make
// your code look neat and tidy.  It is important to have neat code so that
// you or the next person in line (like a coworker or college professor) can
// read it and tell what it does.  Of course you probably won’t ever have to
// write as many comments as I have in this file.

int counter; /* This is a variable (just like math) declaration.  In this case,
I specified that it is an integer (positive or negative whole number).  It’s
like saying "Let there exist an integer named ‘counter’".  There are a few
options for variable types, such as, but not restricted to:
    integer => int
    long integer (for BIG numbers) => long
    character => char
    floating point (number with a decimal) => float
    double-precision floating point (more significant figures) => double
    boolean (either 1, true, or 0, false) => bool
Every variable must be declared with a type.  That’s why C++ is called a
"strongly typed" language.  Also, variable and function names must start with a
letter but can have letters, numbers, or _underscores_ afterwards.  C++ is
case-sensitive, so capitalization matters every time.  It is a useful
convention to capitalize the beginning of each new word in a name, as below. */

char aLetter = ‘j’;  /* Variables can be given values when they are declared.
The assignment operator for C++ is the equals sign.  The assignment operator
always takes two things, the left part and the right part, and assigns the
value of the right part to the variable on the left (right to left evaluation).
Character values are denoted by having single-quotes around a single
letter, number, or symbol.  Characters are different than strings. */

/* counter and aLetter are both "global" variables because they were declared
outside of any functions.  This means that any part of the program can access
them and change them.  Global variables aren’t always a good idea, though,
because they are hard to recognize in code that refers to them all
of a sudden.  Variables declared inside a function are called "local"
variables.  These will always be deleted when the function finishes unless
you do something fancy (We’ll see some of this later).
*/

//  Here we will declare the functions we will be using in our program.
// These are just the declarations.  They tell the compiler that the function
// exists.  Later, we must define each function so that we can actually use it.

/* I want just1() to always give me back the number 1.  Pretty useless, yes,
but it illustrates a few things about functions.  The name of a function,
like just1(), should always say something about what the function does.  
A function named q1342g() won’t help me at all.  It’s also good to write a
quick comment next to a function that tells what it does. */

int just1()
{
    //Function code goes here
   
    return 1;
}

/* Functions are called (used) in this way:
     just1();
 
  But this doesn’t do much for us, really.  The "int" specifies the return
type.  This means that when I call just1(), then an integer will pop right
out when the function ends.  That integer would just be discarded if we don’t
assign it to a variable.  The integer can be caught with the assignment
operator like so:
       int result = just1();
       
  After the return type comes the name followed by parentheses.  Inside the
parentheses is a list of whatever you want the function input to be
(called function arguments).  There are no arguments for just1() though.
*/

/* It is quite important (and good coding style) to write
"prototype declarations" of functions.  If a declaration isn’t found before
you try to use a function, C++ won’t know what you’re talking about.  It’s
like referring to a joke that you haven’t told yet.
*/

// This is a prototype declaration for add1()
int add1(int num); /* I want this function to take a number I give to it, add
one to it, and return the result.  num is an integer that I will provide
whenever I use add1().  When I do call add1() and give it an integer, such
as…
         add1(4);
  …then the value 4 is bound to num which is then used within add1().  I could
even write add1(ONE);, using the preprocessor to convert ONE to 1. */

void countDown(int count); /* Here’s a very fancy function.  I want it to
print to the screen a list of numbers starting with one I give it and descending
(decrementing) until it reaches zero.  The return type, void, means that the
function will not return a value at all.  That means that the function must
perform a useful side-effect like changing a variable or in this case, printing
to the screen.
*/

/*  You can ignore the following function declarations for now.  They’ll be
used later to explain the topics in this tutorial.  You can use this list as
an index if you wish.
*/

void choice();

void operators();  // +, -, *, /, =, etc.
void stdPut();  // cout and cin
void logic();  // if (conditionals), &&, ||, ==, !, !=
void controls();  // loops with while, do while, and for
void arrays();  // arrays[] as lists of variables
void stringClass();  // Explaining the string class
void randomStuff();  // rand() and random number generation
void structKeyword();  // Structures and struct, the precursor to classes
void recursion();  // Looping without loops, function self-calls
void pointers();  // -> memory addresses
void references();  // An easier way to pass by reference
void functionOverloading();  // functions with nearly the same name
void scope();  // local vs. global, precedence rules
void dynamicMemory();  // new and delete memory management
void classes();  // what makes C++ better than C, classes and inheritance

class Junk
{
      int j;
};

int fact(int num);
void square(int a);
void squarePtr(int* x);
void squareRef(int& x);
bool equal(int a);
bool equal(int a, int b);
bool equal(int a, int b, int c);
bool equal(char a, char b);

/*
 Here’s where the fun begins.  The main() function is the entry point of
the program whereas everything up to this is just being held onto for use
in this function.  It’s a good idea to type it
as "int main(int argc, char *argv[])" because then it will return an integer
value to the operating system telling whether or not there was an error and
the arguments afterward give you the ability to catch command-line arguments
(like when you use "Run… c:\test.exe fps toilet" where fps and toilet are
command-line arguments).  You can sometimes put just void main(), but SDL, the
graphics library, requires all this stuff.  Like all function definitions,
main() must have wiggly brackets {}, aka braces, after it.  These braces
contain the statements to be executed when the function is run.
*/

int main(int argc, char *argv[])
{
   
                           /***********
    Let’s go over exactly what code you need for your program to compile.
    First, you need to #include the files that have code that you’ll be using.
    Next, you will usually need the ‘using namespace std;’ line.  Then, you
    need a main() function with a code block ( code surrounded by {} curly
    braces ).  Lastly, make sure your code is correct with semicolons ; after
    every necessary line and you return from main() cleanly.
                                       ************/

                                       
         // Check out GoodExample.cpp if you want to see an example of a
         // pretty basic program.
         // This JDTutorial.cpp is a full program as well, but is very cluttered
         // with tutorial comments.
   
    /*
    My main() is pretty lame.  A main() could be the whole program,
    but mine just organizes the rest of the program.
    */

    srand(time(NULL));  // This is explained in randomStuff()
   
    choice();
   
    system("PAUSE");  // This is an inefficient but very simple way to pause
    // the program.  It’s a call to the operating system and is a little
    // wasteful.  It’s often used in main() to keep the program window open, but
    // some compilers do not need this command to do that.
    return 0;  // No problems running, so return 0 to the operating system.
    // This is the end of the program.  Once main() returns, it’s all over.
    // The return keyword is how you stop a function from continuing and how
    // you can make it give you a value (unless it’s void).  return also
    // accepts variables.  For void functions, just type ‘return;’ to end it.
    // Continue on below for the rest of the tutorial.
   
}  // END int main(int argc, char *argv[])  <- Though this may be
   // unnecessary since main() is so short, it is a good idea to label the end
   // of large blocks of code (like functions).

void operators()
{
     
     /*
     Operators in C++ are those symbols that change or eventually give values,
     again, just like in math class.
     */

     int answer;
     int a = 6;  // The assignment operator, as you’ve seen.
     int b = 4;  // Never try to use an uninitialized variable.  You’ll get
                 // lots of errors.
     
     // (!)  <- Look for this symbol later in the tutorial!
     answer = a + b;   // This will evaluate and set the value of answer to 10
     // (!)
     answer = a – b;   // Answer equals 2
     // (!)
     answer = a * b;   // Answer equals 24
     // (!)
     answer = a / b;   // Equals… 1?  Yep, this is integer division!
     // (!)
     answer = a % b;   // This is "modulo", which gives the remainder of
                       //integer division.
                       // a % b = 2
     // (!)
     // Modulo is a powerful operator.  It can do lots of fun stuff.
     // You’ll see more in randomStuff(), but keep in mind that because
     // modulo is based on division, the result is ALWAYS less than the
     // right side (in this case, "b").
     
     // Just below this comment, see if you can make answer equal 12 by
     // modding two integers.  Then write one that equals zero.
     
     // C++ has some handy shorthand operators as well.
     // From up top a = 6, b = 4.
     // (!)
     a = a + b; // This is the same as…
     // (!)
     a += b;  // This.
     // (!)
     // Notice now that a = (a + b) + b = 14
     a -= b; // Now a = 10
     // (!)
     a *= b; // a = 40
     // (!)
     a /= b; // a = 10
     // (!)
     // The increment and decrement operators are useful too.
     a++; // a = 11
     // (!)
     a–; // a = 10
     // (!)
     // These are in the postfix position, but you can also write them in the
     // prefix position like so:
     ++a;
     // (!)
     –a;
     // (!)
     // The difference is in when they evaluate.
     // a++, the postfix notation of the increment operator, will add one to
     // the variable ‘a’ after the whole line has been performed by the program.
     // ++a, the prefix notation of the increment operator, will add one to
     // the variable ‘a’ immediately and thus before anything else on the line
     // tries to work with it.
     
     
     // Precedence
     
     /*
     Every operator has a preset level of precedence.  This tells which operator
     "precedes" another particular operator.
     For instance, multiplication has a higher precedence than addition.
     Thus, a + b * c
       evaluates like a + (b * c).
       ’b’ and ‘c’ get multiplied before ‘a’ is added.
     Just as I did here, you can make the precedence of your statements clearer
     or cause the precedence to work the way you want it to by using parentheses.
     
     If you look at (a + b) * c,
       this evaluates (a + b) first, then multiplies that result by ‘c’.
       
     The precedence of operators is not usually a big deal, but many new
     programmers will forget that multiplication and division have higher
     precedence than addition and subtraction.
     
     If you need to know any other precedences, you can just search online for
     a C++ precedence table.  Otherwise, you can always use parentheses.
     
     */

     
     
     // Here’s a little test that you can skip if you want
     //  (or just run the program with the task done from the next section…)
     a = 6;
     b = 4;
     answer = 3 * a++ + add1(6) – ++b / 5 + –b + b++;  // Ooh, nice and complicated.
     // It helps to clarify with parentheses sometimes.
     // answer = (3 * a++) + add1(6) – (++b / 5) + –b + b++;
     // Now what is the answer?  a++ increments ‘a’ _after_ the statement is
     // evaluated.  ++b increments ‘b’ _before_ anything else happens.
     // What will be the values of answer, a, and b?
     // (!)
     
}  // END void operators()

int add1(int num)
{return num+=1;}

void stdPut()
{
    // Stuff in this section requires #include <iostream>
     
     /* Do you remember way up there when we #included <iostream>?  That file
    includes two nice objects that we’ll use a lot, cin and cout, console
    input and output objects.  We’ll be getting to the definition of objects
    when we start talking about classes later.  For now, let’s truck along. */

   
    cout << "Hello World!" << endl;  /* The console that cout refers to is that
    ugly MSDOS prompt window that Windows still uses.  The console will boot
    up with the start of the program and then display "Hello World!".  cout
    uses the << left redirect operator.  You can think of it as arrows pointing
    in the direction the data will move, like it takes all the words and sends
    them to the screen.  cout accepts strings like "Hello World!" and standard
    variables.  The keyword "endl" means end line.  It’s like the computer
    presses the return key to start a new line.    
    */

   
    //Here we’ll output some other stuff.  (aLetter is still a global variable)
    cout << endl << aLetter << "onny d" << 3 + 2 << endl;  //jonny d5
   
    // For some practice (and to make the program more useful), go back up to
    // operators() and replace the commented (!) symbol with some uncommented
    // code that will display some useful variables to know at each point.
    // Your best friends will be named "cut" and "paste".
   
   
    /*
    As I said above, <iostream> also includes "cin", the console input object.
    */

    int number;
    cout << endl << "Think of a number… (and enter it)" << endl;
    cout << "->";  // Always prompt for an input.  The user won’t know what
                   // to do otherwise.
    cin >> number;  // The data goes from the input to the variable.
   
    cout << endl << "With my mystical abilities, I have divined that";
    cout << endl << " you chose the number " << number << "!" << endl;
   
    // I personally never use the old C way of collecting input, but I still
    // frequently use C’s output command.
    printf("This is how C programmers had to do output.\n");
    printf("They also knew that %d is your number…\n", number);
    aLetter = ‘a’;
    printf("This is about %d times as %cnnoying!\n", number, aLetter);
    /*
    printf() uses escape characters to represent where info should be inserted.
    As you can see above, \n (backslash n) gives a carriage return, %d is the
    escape for integers, %f does floats and doubles, and %c escapes for
    characters.  A bunch of other escapes are out there.
    */

   
    float pi = 3.14;
    printf("PI = %.2f\n", pi);
    printf("PI = %.4f\n", pi);
    printf("PI = %f\n", pi);
   
   
    cout << "End this line\n";  // You can still use \n with cout if you prefer
                                // it instead of ‘endl’.
   
    // I mostly use printf() with SDL.  SDL has it set that printf() and
    // cout send text straight to an output text file to be read later.  This
    // is pretty useful for debugging (fixing) my programs.
   
    /*
    For certain special characters, you’ll have to use a backslash to show C++
    that you want the actual character.  Plus, since backslash does this special
    trick, you have to use a backslash to escape a backslash.
    */

   
    cout << "Junk coming… \"c:\\cow\\\"" << endl;
    // That’s about all you need to know about input/output until we
    // get to classes.  It wasn’t so bad, was it?
   
}  // END void stdPut()

void logic()
{
    /*
    Logic is the key to having a program that does what you want it to do.
    C++ has all you need to build up your ideas into code.  Booleans are
    commonly used in many languages.  A boolean has only two possible
    values: 0 or 1.
    */

   
    bool test = 1;
   
    // ‘if’ is C++’s basic conditional.  You use conditionals every time you say
    // "If pigs could fly, then I’d be a pig, or else I’d fly instead.".
    // "if" must always be followed by a parenthesized statement that evaluates
    // to a boolean.  "true" is a C++ keyword that evaluates to 1.  "false",
    // of course, evaluates to 0.  Any integer can be used for the boolean
    // test statement because C++ thinks of 0 as meaning false and any other
    // number meaning true.  Since "true" (or 1) is the test parameter, the
    // "then" part will always execute.  In C++, the "then" part can be either
    // a _line_ of code or a _block_ of code.  This one uses a line.
     if (true) cout << "First \"if\" statement" << endl;
     
     
     // Here’s a block.  Blocks are multiple code lines enclosed in {}
     if (test)
     {
              cout << "Second \"if\" statement" << endl;
              test = 0;
              cout << "Test = " << test << " now." << endl;
     }
     // The "else" keyword executes it’s code when a directly preceding if’s
     // test is false.
     else
     {
         cout << "That was false?" << endl;
     }

     // The operators == && || != > < >= and <= compare two arguments and
     // return a boolean value. The operator ! negates a boolean value (changes
     // it from true to false or from false to true).
     if ( 4 == 3 ) cout << "equals" << endl;
     if ( 1 && 0 ) cout << "and" << endl;
     if ( 0 || 1 ) cout << "or" << endl;
     if ( "table" != "table" ) cout << "not equal" << endl;
     if ( 22 > 344 ) cout << "greater than" << endl;
     if ( 1 < (1+1) ) cout << "less than" << endl;
     if ( 12 >= 12 ) cout << "greater than or equals" << endl;
     if ( 72 <= 56 ) cout << "less than or equals" << endl;
     if (!test) cout << "not" << endl;
     
     // For fun, try making all of the above statements evaluate to true and
     // print their messages without changing the operators.
     
     
     
     int difficulty;
     cout << "Choose a difficulty level: ";
     cin >> difficulty;
     if ((difficulty < 0) || (difficulty > 5))
     {
         cout << "That was not a choice for difficulty."
              << endl << "No switch for you!" << endl;
     }
     else
     {
         /* The "switch" statement is a way to check a single variable for lots
         of values.  After each "case" is the value it checks for.  Every case
         set needs a "break" statement.  "break" is a way to end a control
         structure, like this "switch" statement.  Once "break" gets executed,
         none of the other cases are checked.  The default statement is
         used when none of the cases match. */

         switch(difficulty)
         {
         case 1:
              cout << "Diff = 1" << endl;
              break;
         case 2:
              cout << "Diff = 2" << endl;
              break;
         case 3:
              cout << "Diff = 3" << endl;
              break;
         default:
              cout << "That’s too difficult!" << endl;
         }
   
    }
}  //END void logic()

void controls()
{
     /* Though "switch" is a control statement, it is hardly as popular as the
     loop statements: while, for, and do while. */

     int countDown = 10;
     // "while" is the most common loop.  It uses a boolean test, just like
     // the "if" statement, but it executes it’s block of code and then performs
     // the test again.  If it’s still true, it keeps looping.  Try to be
     // careful with loops.  A little typo can cause an infinite loop which can
     // crash the program (alerting the operating system) or cause you to ctrl-
     // alt-delete the whole thing.  Typically, you don’t want to use something
     // that always evaluates to "while (1)".  Even so, you can use the "break"
     // command to escape such a loop.
     
     while (countDown–)  // Run the program and check this one out.
     {
           cout << countDown << endl;
     }
     
     // It performs the test before starting the loop, so the full countdown
     // isn’t shown.
     
     system("PAUSE");
     cout << endl;
     countDown = 10;  // Reset the count.
     
     // "do while" executes the loop at least once before testing it.
     do
     {
           cout << countDown << endl;
     }
     while (countDown–);  // Since "while" doesn’t have a block after it,  
                           // you’ll need a semicolon to end the statement.
     
     
     char letter = ‘a’;
     int n = 0;
     
     while (n < 26)  // A counting loop.
     {
           cout << letter;
           letter++;  // Did you know you can do arithmetic on letters?
           n++;
     }
     
     
     letter = ‘A’;  // Reset letter.
     /* Most programming languages include a convenience loop statement named
     "for".  "for" has three distinct code parts instead of a test.  The first
     part is the initialization, where you set a variable.  The second part
     is the test statement.  The last part is the iterator, where it changes a
     variable.  Semicolons are always used to separate these parts.  So the
     initialization is executed only once, right at the start while both the
     test and the iterator are run after each loop.
     
             init
               |       test
               |        |   iterator
               |        |      |            */

     for (int i = 0; i < 26; i++)
     {
         cout << letter;
         letter++;
     }
     cout << endl;
     
}  // END void controls()

void arrays()
{
     /*
     C++ has a good way to store lots of information.  It also does this very
     efficiently.
     */

     
     // You can declare multiple variables like this:
     int num1, num2, num3, num4, num5;
     
     // And you can initialize them together:
     num1 = num2 = num3 = num4 = num5 = 3;
     cout << num1 << ", " << num2 << endl;
     
     // But you wouldn’t want to clutter your code with tons of variables…
     // Why not use an array?
     int someArray[40];
     /* Arrays use this notation where the number inside the square brackets
     indicates how many variables you’re storing.
     */

     
     // Arrays can be initialized right away…
     int otherArray[10] = {0};  // Shortcut to set all to 0
     int anArray[] = { 7, 1, 4, 16, 94 };
     
     // Or each element can be initialized later…
     // To access a particular element of the array, we indicate the index.
     cout << "Index 3: " << anArray[3] << endl;

     // The confusing part is that the indices of an array start at 0.  That
     // means that the above statement would print 16.
     //         indices:  0  1  2   3   4
     // int anArray[] = { 7, 1, 4, 16, 94 };
     
     for (int i = 0; i < 4 ; i++)  // Start at index zero.
     {
         cout << anArray[i] << endl;
     }
     
     // Be careful not to overrun the array.  You’ll encounter weird results
     // and very likely cause an error if you use anArray[7] when anArray has
     // only five elements.
     
     // C++ can use arrays to form strings of characters.  Instead of filling
     // all of the available spaces with data, however, it needs to use the
     // last element as an "end of string" character, ‘\0′.  This is also
     // called the "null terminator", "null zero", or "zero terminator".  If
     // the compiler doesn’t find this character in the array, it keeps
     // reading (or writing!) into other parts of memory (overruns the array).
     
     char someString[6] = "Hello";  // This means to only use 5 letters!
                            // You can assign literal strings to these arrays.
                            // C++ will take care of the null terminator
     
     // That’s too confusing, so you can make a character array figure out how
     // much memory it needs on it’s own, but only when you first create
     // the array.
     char anotherString[] = "How many elements does this have?";
     
     int count = 0;
     int i = 0;
     while (anotherString[i] != \0)
     {
           count++;
           i++;
     }
     cout << "anotherString has " << count << " elements." << endl;
}  // END void arrays()

void stringClass()
{
     // Stuff in this section requires #include <string>
     
     /*
     C++ Strings are way easier than C strings to understand and use.  Since
     it is a string class, it is loaded up (down?) with tons of ways to work
     with the information.  We’ll focus on the basics that will get you almost
     anywhere with C++ strings.
     */

     string word;
     
     word = "We shall overcome!";
     
     // Particular characters in strings can be accessed just like arrays.
     cout << word << endl;
     cout << word[0] << word[1] << " " << word[5] << word[6] << word[7]
          << " " << word[9] << word[12] << word[13] << word[17] << endl;
     
     // You can easily concatenate (combine) strings with the + operator.
     string word2 = "  Unless otherwise noted.";
     
     cout << word + word2 << endl;
     
     word += word2;
     
     cout << word << endl;
     
     /* Because string is a class, objects (such as word and word2) each have
     access to special string functions.  They are accessed with the dot (.)
     operator.
     The empty() function returns a boolean value telling whether or
     not the string is empty (useful for loops).
     */

     if ( word.empty() ) cout << "EMPTY!" << endl;
     
     // The first argument to erase() is the index to start from.  The second
     // argument is the number of characters to erase.  All characters after
     // the erased ones slide right down to replace them.
     word.erase(3, 6);
     cout << word << endl;
     
     // insert() takes an index and a string, squeezing that string into the
     // point the index represents.
     word.insert(7, word2);
     cout << word << endl;
     
     // length() takes no arguments and just returns the size of the string.
     word.erase( 0, word2.length() );
     cout << word << endl;
     
     /* Strings can be compared with the ==, <, >, <=, >=, and != operators.
     The quirk here is that it’s alphabetic comparison.
     "abc" is greater than "jvc"
     "ghi" < "ghj"
     */

     
     if (word != word2)
     {
          cout << "word != word2" << endl;
     }

}  // END void stringClass()

void randomStuff()
{
     /*
     The rand() function is C++’s way of getting a random number.  In main(), we
     used a function call that looked like this: srand(time(NULL))
     "srand" stands for "seed random [number generator]".  Seeding something
     means to initialize it to a value.  "srand" gives rand() a different
     starting place than it has by default.  The reason this matters is because
     rand() is not actually random.  rand() draws from a big list of numbers and
     gives them to you in order.  Without seeding rand(), it will always start
     at the same place.  In fact, this won’t do the job alone, but when we seed
     rand() with a constantly changing number (aka time), then we can get fairly
     reliable random numbers.  Here’s where one great use of the modulus (%)
     operator is.  We can use it to restrict the range of possible numbers.
     Modulo will return the remainder of integer division.  It’s based on
     division, so the result ranges only from 0 to the right side value.
     */

     
     int rando = rand()%99 + 1;  // Gives a number 1-100
     
     cout << rando << endl;
     
     rando = rand()%2;  // 0-1
     cout << rando << endl;
     rando = rand()%65;  // 0-64
     cout << rando << endl;
     rando = rand()%4000;  // 0-3999
     cout << rando << endl;
     
     
     int strength = (rand()%6 + 1) + (rand()%6 + 1) + (rand()%6 + 1);  // 3-18
     
     int damage = 1 + rand()%strength;
     
     int low = 55;
     int high = 231;
     
     int lowToHigh = rand()%(high + 1 – low) + low;
     
}  // END void randomStuff()

void structKeyword()
{
     /*
     Structures are handy little things similar to arrays in concept.  Arrays
     are collections of variables of the same type, whereas structures hold a
     bunch of variables of any types (even other structures) that you want to
     have grouped together.
     */

     
     struct ITEM  // How about an item structure?
     {
            int type;  // Which item is it?
            int uses;  // How many times can I use it?
            bool ready;  // Can I use it now?
            bool equipped;  // Do I have it at hand?
            string itemName;
     };
     
     /*  Structs are like type definitions.  Now that we told the compiler what
     this struct is, we can make an instance of one.
     */

     
     ITEM gravyBoat;
     
     gravyBoat.type = 42;
     gravyBoat.uses = 1;
     gravyBoat.ready = 1;
     gravyBoat.equipped = 0;
     gravyBoat.itemName = "gravyboat";
     

     struct PLAYER  // But what use is an item without a player to use it?
     {
       int hp;
       int magic;
       bool active;
       int location;
       ITEM item;
     };
     
     struct GRID  // Here’s a type of grid structure.
     {
       int x,y;   // We’ll store some position data
       bool active;  // Does the grid position exist (say, on this map)?
       bool occupied;  // Is there something already in this grid position?
     };
     
     
     GRID grid[15];  // Now we have a grid with 16 possible positions.
     
     PLAYER player1;  // I don’t feel like initializing everything, but remember
     player1.hp = 50; //   to never use something that hasn’t been initialized.
     player1.location = 10;
     player1.item.uses = 1;
     player1.item.itemName = "gravyboat";
     grid[player1.location].occupied = 1;
     
     
     player1.item.uses–;
     cout << "You’ve been " << player1.item.itemName << "ed!  …At grid number "
          << player1.location << endl;
         
     /*
     Structures are the precursors to a very important aspect of C++ and most
     other programming languages…  Classes.  Classes will be covered in just
     a few sections, but I’ll give you a little clue to one of their powerful
     features…  Classes are like structures that can contain functions.
     */

     
}  // END void structKeyword()

void recursion()
{
     /* Recursion is a technique that requires a lot of practice to really
     figure it out.  Recursion is when a function calls itself.  There are
     literally a limitless number of reasons to do this.  We’ll check out a few.    
     */

     
     // Take a look below recursion() for the definition of this function:
     countDown(10);
     
     // As you can see, countDown() takes an integer and prints all the numbers
     // down to zero.  This is an example of a recursive function that relies
     // on "side-effects" to produce a result.  Side-effects are those that
     // come about by running a function and not just by dropping and catching
     // functions’ return values.
     
     // This one is a recursive function that hints at the power of recursion.
     int number = 5;
     int answer = fact(number);
     
     cout << "Factorial of " << number << " equals " << answer << endl;
     
}  // END void recursion()

void countDown(int count)
{
    cout << count << endl;
    if (count > 0) countDown(–count);
}

int fact(int num)
{
    if (num == 0)  // Ends the recursion…  We know that 0! = 1
    return 1;
   
    return num * fact(num – 1);  // A recursive definition of factorial
                                 // n! = n * (n-1) * (n-2) * … * 1
                                 // The easiest ideas to model are those that
                                 // have a sequence like factorial does.
        // num * fact(num – 1) could be rewritten as:
        //  n  *  (n-1)!
       
    // As you can see (or will hopefully see), every recursive function has two
    // main parts.  It needs something to recurse around (num*fact(num-1)) and
    // it needs something to end the recursion (if (num==0) return 1;).  Lots
    // of recursive functions have other parts, but they all have those two
    // in common.
}

void pointers()
{
     /* Computers store running program data in what is called "Random Access
     Memory" or RAM.  How does the computer keep track of all the stuff in RAM?  
     It knows that the memory is set up so that a single ‘memory location’ can
     be accessed by referring to its ‘memory address’.  C++ has a very low-level
     (very close to how the computer actually works… and consequently kind of
     hard to deal with, but very efficient) way of working with memory
     addresses.  We can store the address of some information in a variable
     called a ‘pointer’ (it points to actual data).
     */

     
     int* intPointer;  // This can point to an integer… but doesn’t yet.
     char* charPointer;  // This can point to a character.
     
     // Pointers are denoted with a type like: int*
     // This is their actual type now.  Instead of being just of type ‘int’,
     // intPointer is of type ‘int*’.  It’s best not to confuse this use of the
     // asterisk ‘*’ with what is used next.  Think of this as part of the
     // type’s name.
     
     int integer;
     char character;
     
     intPointer = &integer;  // Here we use the ampersand ‘&’ operator.  This
                     // returns the address of the variable it is put in
                     // front of.  You can think of this as the "address of"
                     // operator.  Make sure you initialize your pointers to
                     // an actual address like this before you try to use them.
                     // That could cause a crash of your program.  Remember
                     // that because it is a pretty common mistake.
     
     charPointer = &character;
     
     *intPointer = 5;  // This assigns the value 5 to the place that is pointed
                       // at by intPointer.  This place is also named by
                       // the variable "integer".
                       
     /*  The asterisk ‘*’ or star is called the dereference operator.  This means that
     it actually returns the data held in memory.  *intPointer is like the
     variable name of the data in that location.  You can remember what the *
     does if you think of it as the "stuff at" operator.  Then it means the
     "stuff at" the address intPointer.  Now we can really use these pointers.    
     */

     
     *charPointer = ‘g’;
     
     if (*intPointer / 5 == 1) *charPointer = ‘p’;
     
     /* Now why don’t we just use normal variables for this?  Well, we would.
     But if you’ve just been following along in this tutorial, there’s something
     you probably haven’t noticed.  Let’s call a function.
     */

     
     int a = 3;
     square(a);  // This function takes an int and sets it to equal itself
                 // times itself.  It’s declared void, so there’s no
                 // returning data.
                 
     cout << a << endl;  /* This prints ’3′, the exact value we passed in!  
                          This is because we did something called
                          ‘pass-by-value’.  We passed the variable ‘a’ to the
                          function square().  square() made a copy of the
                          value stored in ‘a’.  As you can see below this
                          section, the function square() names this copied
                          variable ‘x’.  It then sets ‘x’ to equal x * x.
                          Obviously, we’re not working with ‘a’ anymore.  
                          That’s why it didn’t change when we wanted it to.
                         
                          So we’d rather use ‘pass-by-reference’. Take a look
                          at squarePtr().  Here we’re sending the address of a
                          variable.  Let’s try using it.
                         */

     
     int* aPtr = &a;;  // Here’s a pointer that we’ll assign to the address of ‘a’.
     
     squarePtr(aPtr);
     
     cout << a << endl;  // Now we get our 9!
     
     squarePtr(&a);  // Another way to do this is to directly send the address
                     // of ‘a’.  This doesn’t require an extra pointer to use.
     
     cout << a << endl;
     
     // A few uses for pointers will be expanded in the dynamicMemory() section
}  // END void pointers()

void square(int x)
{
    x *= x;
}

void squarePtr(int* x)
{
    *x *= *x;  // Kinda messy here, but we’re working with the "stuff at" x.
}

void references()
{
     /*
     References are very much like pointers, but they make functions like
     squarePtr() much easier to design.  A reference is just another name for
     the memory address of a variable.
     */

     
     int z = 2;
     
     int& aReference = z;  // Here’s a reference.
     
     /*
     For the most part, references are used for functions that will take and
     change a given variable.  Another use is for ‘aliases’, but they aren’t
     that useful, so I won’t go into them any further.
     
     Let’s try our nice, new, and clean squareRef() function.
     */

     
     int var = 12;
     
     squareRef(var);
     
     cout << var << endl;
     
     // As you can see, I didn’t have to mess with my variable at all!
     // How convenient!
     
     
     
}  // END void references()

void squareRef(int& x)  // Notice the difference?
{
     x *= x;
}

void functionOverloading()
{
     /*
     Function overloading is much easier and more useful than it sounds.
     Overloading a function is to use the same function name for multiple
     functions.  This comes in handy when you want to do similar tasks with
     different variable types without having to come up with (and remember) a
     unique name for each function.
     
     If you look at the ‘equal()’ functions below this section, you can see
     some overloaded functions.
     We want to know if some integers are equal, but what if we don’t always
     know how many we’re working with?
     */

     
     int a = 1;
     int b = 1;
     int c = 2;
     
     char cha = ‘@’;
     char chb = ‘@’;
     
     cout << equal(a) << endl  // always true (1)
          << equal(a, b) << endl  // true
          << equal(a, b, c) << endl  // false!
          << equal(cha, chb) << endl;  // true
         
     
     /*
     Thankfully, the compiler is smart enough to recognize it when you use
     different types and different numbers of arguments to functions.  That’s
     what allows for this feature.  Different return types will not disambiguate
     the call on their own, though, so don’t try just that.
     */

     
}  // END void functionOverloading()

bool equal(int a)
{
    return 1;
}

bool equal(int a, int b)
{
    return a == b;
}

bool equal(int a, int b, int c)
{
    return a == b && b == c;
}

bool equal(char a, char b)
{
    return a == b;
}

void scope()
{
     /*
     Scope is a term for what variables you have access to at a certain
     point in a program.
     
     We’ve already talked a little about the ‘global’ scope.
     Global variables can be used anywhere in your program because they were
     declared outside of any function.
     */

     
     //Global variable ‘aLetter’
     cout << aLetter << endl;
     
     char tempLetter = aLetter;
     // This just created a variable that is ‘local’ to the function scope().
     // When this function ends, this variable is automatically deleted.
     // No other function can use ‘tempLetter’ unless I pass it as an argument.
     
     // Here I’m making another local variable and calling equal() with two
     // passed variables.
     bool test = equal(tempLetter, aLetter);
     if(test)
       cout << "These are equal!" << endl;
       
     // You’ll need to be aware of the scope you’re working in when it comes
     // to classes in a couple of sections…
     
}  // END void scope()

void dynamicMemory()
{
     /*
     Dynamic memory is a term for program memory that is not stored at compile
     time.  With the usual variable declarations that we’ve been working with,
     the variables have been hard-coded into the program and will work exactly
     the same for every time the program is run.  If we want to make variables
     that don’t automatically take up space or if, say, we don’t know how many
     variables we need (in the case of an array), then we need to use C++’s
     dynamic memory operators, ‘new’ and ‘delete’.
     
     Simply put, ‘new’ creates a new variable and ‘delete’ frees the memory
     that is used by that variable so that the memory can be used again before
     the program closes.
     
     So, let’s try making an array of an unknown size.
     */

     
     int numElements = 0;
     while(numElements == 0)
     {
     numElements = 0;
     cout << "Hey, tell me how many variables we’ll have." << endl;
     cin >> numElements;
     }
     // Arrays are actually pointers to the first element of the array, so we
     // can write them like pointers:
     int* anArray = new int[numElements];
     
     // Let’s initialize the elements
     for(int i = 0; i < numElements; i++)
     {
       anArray[i] = 0;
     }
     
     // Now we can use them for whatever
     for(int i = 0; i < numElements; i++)
     {
       cout << "Element #" << i << " = " << anArray[i] << endl;
     }
     
     // Then free the memory when we’re done.
     delete[] anArray;
     
     /*
     To delete an entire array, you have to put those square brackets after
     delete.  If you don’t, it will treat it like a pointer instead of an array
     and will only delete the first element.
     */

     // So, pointers to any other type work like that.
     double* dPtr;
     dPtr = new double;
     // Use it…
     // Then delete it.
     delete dPtr;
     
     /*
     Using ‘delete’ effectively is the main concern for many programs written
     in C++.  If an allocated resource is not freed, then the memory is not
     usable until the program ends.  This is called a "memory leak".  Always
     remember to delete every dynamic variable.  Some programmers even write
     a delete statement immediately whenever they write a new statement so that
     they don’t forget.
     */

     
     
     struct Something
     {
            int type;
            int number;
     };
     
     Something* number1 = new Something;
     
     number1->type = 4;
     
     cout << number1->type << endl;
     
     // Here we used a great little operator, the arrow operator.
     // This is a shortcut to replace the asterisk-dot combo.
     // If we didn’t use this, we would write:
     //              (*number).type = 4;
     //   Since the dot operator has a higher precedence than the dereference
     //   operator, the arrow is much cleaner (and makes me think of "pointer"
     //   anyway).  The arrow "points" to a member.
     
     (*number1).type = 20;
     cout << (*number1).type << endl;
     
     delete number1;
     
     
}  // END void dynamicMemory()

void classes()
{
     //See ClassName.h, the #included header file for the details
     
     
     // Let’s just go through some object handling now.
     
     ClassName* object = new ClassName;
     
     // Use that arrow operator to work in the scope of the object.
     object->data = 3;
     
     cout << "7 * 2 = " << object->fn(7) << endl;
     
     cout << "Data * 2 = " << object->fn(object->data) << endl;
     
     object->cow();
     
     InheritsFromClassName* anotherObject = new InheritsFromClassName;
     
     // This still has the members of the base class.
     anotherObject->cow();
     
     // But it also has it’s own stuff…
     anotherObject->notCow();
     
     // Here’s a great way to work with inherited classes.
     // It’s part of a topic called ‘Polymorphism’.
     
     ClassName** array = new ClassName*[2];  // Will hold two pointers to
                                             // objects of type ClassName.
     
     array[0] = object;  // This is a ClassName object
     
     array[1] = anotherObject;  // Hey!  This is too (deep down somewhere)!
     
     array[0]->cow();  // Now we can cow() together in an array!
     array[1]->cow();  // But only with members of the array’s class type which
                       // in this case is ClassName.
     //array[1]->notCow(); // ERROR!!  The program sees this as just a ClassName
                     
     // If you definitely know that array[1] is an InheritsFromClassName object,
     // then you can use ‘type-casting’ to change it back into its full
     // abilities.  Type-casting is done by writing a type within parentheses
     // and putting that before the variable that you want to convert to
     // that type.
     InheritsFromClassName* ifcn = (InheritsFromClassName*)array[1];
     
     // Now we can use the InheritsFromClassName members!
     ifcn->notCow();
     
     // This also works for the primitive types.  Try this if you get warnings
     // from your compiler about incompatible types.
     float flo = 6.0;
     //int q = flo;  // Warning
     int z = (int)flo;
     
     // C++ offers some other cool type-casting operators, but I’ll just show
     // you one pretty useful one.
     // dynamic_cast returns what you would expect from a cast if it is valid,
     // but returns a NULL value if the cast is not valid.
     
     //  dynamic_cast<TYPE>(VARIABLE)
     
     ClassName* cn = new ClassName();
     
     // Junk is a class I defined that just has an integer member named ‘j’
     Junk* junky = dynamic_cast<Junk*>(cn);  // Not a valid cast
     
     if(junky == NULL)
       cout << "Junky NULL\n" << endl;
     else
       cout << "Junky not NULL?\n" << endl;
     
     // dynamic_cast does its work on the fly, so don’t use it too much when
     // you need a program to run fast.
     
     
     /*
     Well, this is the end of the tutorial.  I hope you’ve been able to absorb
     all that and come away with some basic, working knowledge of C++ and
     programming in general.  If you have any questions including any on other
     C++ topics (seen below), just catch me at GrimFang4@hotmail.com
     
     It’s been a pleasure.
     -Jonny D
     
     */

     
     
     /*
     Some Other Topics:
     
       templates
       extern, file splitting
       linked lists, queues, stacks
       bubble sort
       abstract classes, virtual functions
       file streams
     */

     
}  // END void classes()

void choice()
{
     int choice = -1;
     while (choice != 16)
     {
     cout << endl << "Type a choice and press enter…" << endl;
     cout << endl << "1 = Operators  "
                  << "6 = String Class    "
                  << "11 = References" << endl
                  << "2 = Std ‘Put   "
                  << "7 = Random Stuff    "
                  << "12 = Function Overloading" << endl
                  << "3 = Logic      "
                  << "8 = Struct Keyword  "
                  << "13 = Scope" << endl
                  << "4 = Controls   "
                  << "9 = Recursion       "
                  << "14 = Dynamic Memory" << endl
                  << "5 = Arrays     "
                  << "10 = Pointers       "
                  << "15 = Classes" << endl
                  << "                                   16 = Exit Testorial!" << endl << endl << "->";

     cin >> choice;
     switch(choice)
    {
    case 1:
         operators();  // +, -, *, /, =, etc.
         break;
    case 2:
         stdPut();  // cout and cin
         break;
    case 3:
         logic();  // if (conditionals), &&, ||, ==, !, !=
         break;
    case 4:
         controls();  // switch, loops with while, do while, and for
         break;
    case 5:
         arrays();  // arrays[] as lists of variables
         break;
    case 6:
         stringClass();  // Explaining the string class
         break;
    case 7:
         randomStuff();  // rand() and random number generation
         break;
    case 8:
         structKeyword();  // Structures and struct, the precursor to classes
         break;
    case 9:
         recursion();  // Looping without loops, function self-calls
         break;
    case 10:
         pointers();  // -> memory addresses
         break;
    case 11:
         references();  // An easier way to pass by reference
         break;
    case 12:
         functionOverloading();  // functions with nearly the same name
         break;
    case 13:
         scope();  // local vs. global, precedence rules
         break;
    case 14:
         dynamicMemory();  // new and delete[] memory management
         break;
    case 15:
         classes();  // what makes C++ better than C, classes and inheritance
         break;
    case 16:
         break;
    }
    if (choice != 16) system("PAUSE");
    }
}  // END void choice()
 




Files:
jonny-ds-c-tutorial.zip

Share and Enjoy:
  • Digg
  • del.icio.us
  • DZone
  • MisterWong
  • Reddit
  • StumbleUpon
  • Technorati
  • Slashdot
  • LinkedIn
  • MySpace
  • Yahoo! Buzz

Did you like this tutorial/blog post? Feel free to donate to keep more comin', and have more contests.

Advertisement

2 comments

  1. Mohamed says:

    Good job, keep it up! =)

  2. Johnathan says:

    Nicely done…

Leave a Reply